package com.jadows.tdog.server.handler;


import com.jadows.tdog.server.listener.ChannelEventListener;
import com.jadows.tdog.util.NettyUtil;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler;
import io.netty.handler.timeout.IdleState;
import io.netty.handler.timeout.IdleStateEvent;
import lombok.extern.slf4j.Slf4j;

import javax.annotation.Nonnull;
import java.util.concurrent.ExecutorService;

/**
 * 线程安全 每个channel 一个 handler 实例
 *
 * @author taojiacheng
 */
@Slf4j
public class ChatServerChannelHandler extends SimpleChannelInboundHandler<TextWebSocketFrame> {

    protected final ChannelEventListener eventListener;
    protected final ExecutorService publicExecutor;
    protected String remoteAddr;

    public ChatServerChannelHandler(ChannelEventListener eventListener, ExecutorService publicExecutor) {
        this.eventListener = eventListener;
        this.publicExecutor = publicExecutor;
    }

    /**
     * 客户端连接建立时
     *
     * @param ctx ChannelHandlerContext
     * @throws Exception Exception
     */
    @Override
    public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
        this.remoteAddr = NettyUtil.getAttr(ctx.channel(), NettyUtil.IP);
        eventListener.onAdded(ctx);
    }

    /**
     * 客户端掉线
     */
    @Override
    public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {
        eventListener.onRemoved(ctx);
    }

    /**
     * 连接断开
     */
    @Override
    public void channelInactive(@Nonnull ChannelHandlerContext ctx) throws Exception {
        super.channelInactive(ctx);
        log.debug("channel inactive [{}]", ctx.channel());
        eventListener.onDisconnect(ctx);
    }

    /**
     * 读取消息
     */
    @Override
    protected void channelRead0(ChannelHandlerContext ctx, TextWebSocketFrame msg) throws Exception {
        eventListener.onMessageArrived(ctx, msg.text());
    }


    @Override
    public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
        if (evt instanceof IdleStateEvent idleStateEvent) {
            // 读空闲
            if (idleStateEvent.state() == IdleState.READER_IDLE) {
                // 关闭用户的连接
                eventListener.onDisconnect(ctx);
            }
        } else if (evt instanceof WebSocketServerProtocolHandler.HandshakeComplete) {
            // 握手成功
            eventListener.onShakeHandComplete(ctx);
        }
        super.userEventTriggered(ctx, evt);
    }

    /**
     * 异常处理
     */
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
        log.error("exceptionCaught remoteAddr : {}, cause : ", remoteAddr, cause);
        ctx.close();
        ctx.fireExceptionCaught(cause);
    }

}
